package com.magold.game.factory;

import org.andengine.engine.camera.Camera;
import org.andengine.extension.physics.box2d.PhysicsWorld;

import com.magold.event.EventDrivable;
import com.magold.event.EventsProcessor;
import com.magold.game.level.MagoldLevel;
import com.magold.io.XMLReader;
import com.magold.level.ILevel;
import com.magold.level.ILevel.CircuitParamProvider;
import com.magold.level.ILevel.EventParamProvider;
import com.magold.level.ILevelElementLoader;
import com.magold.logic.ISpriteLogic;

public abstract class BaseLogicFactory implements IXMLFactory, ILevelElementLoader {
	private String mLoadableName;
	private ILevel mCachedLevel;
	private EventFactory mCachedParser;

	public BaseLogicFactory(String pLoadableName) {
		mLoadableName = pLoadableName;
	}

	@Override
	public boolean onLoadEntity(XMLReader pReader, ILevel pLoadingLevel) {
		if (!valid(pReader.getNodeName())) return false;

		ISpriteLogic logic = create(pReader);

		if (logic == null) return false;

		float x = pReader.getFloat("x");
		float y = pReader.getFloat("y");

		float rotation = pReader.getFloat("rotation", 0);
		float scale = pReader.getFloat("scale", 1);

		logic.createSceneData(x, y, rotation, scale, pLoadingLevel.getScene());
		PhysicsWorld pw = pLoadingLevel.getPhysicsWorld();
		if (pw != null) logic.createPhysicsData(pw);

		int id = pReader.getInt("id", -1);
		if (id >= 0) {
			pLoadingLevel.putIdentifiedObject(id, logic);
		}

		if (pReader.moveToChild("Event")) {
			updateParser(pLoadingLevel);
			do {
				if (!pReader.getNodeName().equals("Event")) continue;
				mCachedParser.createEvent(pReader, (EventDrivable) logic);
			} while (pReader.moveToNextSibling());

			pReader.moveToParent();
		}

		onLoaded(logic, pReader, pLoadingLevel);

		return false;
	}

	protected void onLoaded(ISpriteLogic pProduct, XMLReader pReader, ILevel pLevel) {
	}

	private void updateParser(ILevel pLoadingLevel) {
		if (pLoadingLevel != mCachedLevel) {
			CircuitParamProvider pCircuitParamProvider = pLoadingLevel.getCircuitParamProvider();
			EventParamProvider pParamProvider = pLoadingLevel.getEventParamProvider();
			EventsProcessor pProcessor = (EventsProcessor) pLoadingLevel.getAttributeValue(MagoldLevel.EVENT_PROCESSER_KEY);
			Camera pCamera = pLoadingLevel.getEngine().getCamera();
			mCachedParser = new EventFactory(pCircuitParamProvider, pParamProvider, pProcessor, pCamera);
		}
	}

	protected boolean valid(String pNodeName) {
		return pNodeName.equals(mLoadableName);
	}

	@Override
	public final ISpriteLogic create(XMLReader pReader) {
		if (valid(pReader.getNodeName())) {
			return createSafely(pReader);
		}

		return null;
	}

	public String getLoadableElementName() {
		return mLoadableName;
	}

	protected abstract ISpriteLogic createSafely(XMLReader pReader);

}
